home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i102: New version of less (less2), Part01/02
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: seismo!lll-crg!csustan!casey
- Mod.sources: Volume 6, Issue 102
- Archive-name: less2/Part01
-
- [ This version of less provides support for "boldening," as in a^Ha^Ha,
- and a "-z" flag to set the window size (for compatiblity with more).
- It also provides a small front-end program for systems/programs that
- don't support the PAGER environment variable. And, as Casey said in
- his cover note to me... "If you can find Mark Nudelman, send him a copy."
- --r$ ]
-
- ---- cut here ---- cut here ---- cut here ---- cut here ---- cut here ----
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # INSTALLATION
- # README-casey
- # README-usenet
- # ch.c
- # command.c
- # funcs.h
- # help.c
- # input.c
- # less.h
- # less.l
- # line.c
- # main.c
- # makefile.bsd41
- # makefile.bsd42
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'INSTALLATION'
- then
- echo shar: "will not over-write existing file 'INSTALLATION'"
- else
- cat << \SHAR_EOF > 'INSTALLATION'
- This is the distribution of "less", a paginator similar to "more" or "pg".
- The manual page is in less.l.
-
- INSTALLATION:
-
- 1. Move the distributed source to its own directory and
- unpack it by running "sh" on the distribution file,
- if you have not already done so.
-
- 2. If your system is System V:
- cp makefile.sys5 makefile
- If your system is Berkeley 4.2bsd:
- cp makefile.bsd42 makefile
- If your system is Berkeley 4.1bsd:
- cp makefile.bsd41 makefile
- If your system is Xenix 3.0:
- cp makefile.xen makefile
- Otherwise, edit the makefile to make the
- system parameters match your system.
-
- These features are selectable at compile time:
- shell escapes (SHELL_ESCAPE)
- editor invocation (EDITOR)
- alternate error message handling (ONLY_RETURN)
- If you want to have any of these features,
- edit the makefile appropriately.
- (If you do not include either SHELL_ESCAPE or EDITOR,
- you may wish to edit the manual page "less.l" to remove
- the references to the "!" and/or "v" commands.)
-
- 3. Type "make" and watch the fun.
-
- 4. If the make succeeds, it will generate a program "less"
- in your current directory. Test the generated program.
-
- 5. When satisfied that it works, if you wish to install it
- in a public place, edit the makefile so that INSTALL_LESS
- and INSTALL_MAN are the proper filenames.
- Then type "make install".
-
- If you have any problems building or running "less",
- you may mail to the author via USENET at:
- ...!tektronix!reed!nsc-pdc!mark
- or ...!ihnp4!nsc!nsc-pdc!mark
-
- Note to hackers: comments noting possible improvements are enclosed
- in double curly brackets {{ like this }}.
- SHAR_EOF
- fi
- if test -f 'README-casey'
- then
- echo shar: "will not over-write existing file 'README-casey'"
- else
- cat << \SHAR_EOF > 'README-casey'
- Monday July 14, 1986
-
- I've made four changes to less:
-
- 1. You can now install the pager_patch program to let you use less as
- your default pager even if the programs you're using don't pay
- attention to the PAGER environment variable.
-
- 2. It's now allowable to invoke less with "-[z]N" to specify the window
- scroll size ala more (note that the "z" may be omitted) - this
- was done for compatibility with more(1) as some programs (ex: msgs)
- called the pager with a window size specification.
-
- 3. Less will now detect "boldfacing sequences" and use the /etc/termcap
- capability "md" and "me" to boldface the corresponding text.
- Boldface sequences are sequences of a character overstruck with
- backspaces (ex: a^Hab^Hb ...). Any number of overstrikes are ok.
- For those whose nroff doesn't generate these sequences for [default]
- boldfacing, look at the file n10-diff for the necessary changes to
- nroff [n10.c].
-
- 4. The manual page has been reformatted to have more boldface sequences
- (some may find my avoidance of ".B", ".I", etc. to be annoying, but
- what the hey, I'll let Mark Nudelman (less's original author) have
- the final decision). I haven't reorganized the command and switch
- descriptions to be in alphabetic order ... Still not sure whether
- that should be done ...
-
- Leith (Casey) Leedom lll-crg.arpa!csustan!casey
- Computer Science Department work: (209) 667-3185
- California State University, Stanislaus home: (209) 634-2775
- Turlock, CA 95380
- SHAR_EOF
- fi
- if test -f 'README-usenet'
- then
- echo shar: "will not over-write existing file 'README-usenet'"
- else
- cat << \SHAR_EOF > 'README-usenet'
- >From sources-request@panda.UUCP Tue Feb 11 15:30:56 1986
- Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site lll-crg.ARpA
- Path: lll-crg!topaz!harvard!talcott!panda!sources-request
- From: sources-request@panda.UUCP
- Newsgroups: mod.sources
- Subject: less part 1 of 2
- Message-ID: <1400@panda.UUCP>
- Date: 11 Feb 86 23:30:56 GMT
- Date-Received: 12 Feb 86 05:00:57 GMT
- Sender: jpn@panda.UUCP
- Lines: 2500
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 120
- Submitted by: ihnp4!nsc!nsc-pdc!rgb (Robert Bond)
-
-
-
- Here is the last distribution of less made by Mark Nudelman to net.sources
- before he left National Semiconductor. Since it is taking so long for him
- to get back on the net, and because lots of folks did not get part 2
- of the last distribution, we have decided to submit less to mod.sources.
- Mark is still promising to return to the net Real Soon Now.
- SHAR_EOF
- fi
- if test -f 'ch.c'
- then
- echo shar: "will not over-write existing file 'ch.c'"
- else
- cat << \SHAR_EOF > 'ch.c'
- /*
- * Low level character input from the input file.
- * We use these special purpose routines which optimize moving
- * both forward and backward from the current read pointer.
- */
-
- #include "less.h"
-
- public int file = -1; /* File descriptor of the input file */
-
- /*
- * Pool of buffers holding the most recently used blocks of the input file.
- */
- #define BUFSIZ 1024
- static struct buf {
- struct buf *next, *prev;
- long block;
- char data[BUFSIZ];
- };
- static struct buf *bufs = NULL;
- public int nbufs;
-
- /*
- * The buffer pool is kept as a doubly-linked circular list,
- * in order from most- to least-recently used.
- * The circular list is anchored by buf_anchor.
- */
- static struct {
- struct buf *next, *prev;
- } buf_anchor;
- #define END_OF_CHAIN ((struct buf *)&buf_anchor)
- #define buf_head buf_anchor.next
- #define buf_tail buf_anchor.prev
-
- /*
- * If we fail to allocate enough memory for buffers, we try to limp
- * along with a minimum number of buffers.
- */
- #define DEF_NBUFS 2 /* Minimum number of buffers */
-
- extern int clean_data;
- extern int ispipe;
-
- /*
- * Current position in file.
- * Stored as a block number and an offset into the block.
- */
- static long ch_block;
- static int ch_offset;
-
- /*
- * Length of file, needed if input is a pipe.
- */
- static POSITION ch_fsize;
-
- /*
- * Largest block number read if input is standard input (a pipe).
- */
- static long last_piped_block;
-
- /*
- * Get the character pointed to by the read pointer.
- * ch_get() is a macro which is more efficient to call
- * than fch_get (the function), in the usual case
- * that the block desired is at the head of the chain.
- */
- #define ch_get() ((buf_head->block == ch_block) ? \
- buf_head->data[ch_offset] : fch_get())
- static int
- fch_get()
- {
- register struct buf *bp;
- register int n;
- register int end;
- POSITION pos;
-
- /*
- * Look for a buffer holding the desired block.
- */
- for (bp = buf_head; bp != END_OF_CHAIN; bp = bp->next)
- if (bp->block == ch_block)
- goto found;
- /*
- * Block is not in a buffer.
- * Take the least recently used buffer
- * and read the desired block into it.
- */
- bp = buf_tail;
- bp->block = ch_block;
- pos = ch_block * BUFSIZ;
- if (ispipe)
- {
- /*
- * The block requested should be one more than
- * the last block read.
- */
- if (ch_block != ++last_piped_block)
- {
- /* This "should not happen". */
- char message[80];
- sprintf(message, "Pipe error: last %ld, want %ld\n",
- last_piped_block-1, ch_block);
- error(message);
- quit();
- }
- } else
- lseek(file, pos, 0);
-
- /*
- * Read the block. This may take several reads if the input
- * is coming from standard input, due to the nature of pipes.
- */
- end = 0;
- while ((n = read(file, &bp->data[end], BUFSIZ-end)) > 0)
- if ((end += n) >= BUFSIZ)
- break;
-
- if (n < 0)
- {
- error("read error");
- quit();
- }
-
- /*
- * Set an EOF marker in the buffered data itself.
- * Then ensure the data is "clean": there are no
- * extra EOF chars in the data and that the "meta"
- * bit (the 0200 bit) is reset in each char.
- */
- if (end < BUFSIZ)
- {
- ch_fsize = pos + end;
- bp->data[end] = EOF;
- }
-
- if (!clean_data)
- while (--end >= 0)
- {
- bp->data[end] &= 0177;
- if (bp->data[end] == EOF)
- bp->data[end] = '@';
- }
-
- found:
- /* if (buf_head != bp) {this is guaranteed by the ch_get macro} */
- {
- /*
- * Move the buffer to the head of the buffer chain.
- * This orders the buffer chain, most- to least-recently used.
- */
- bp->next->prev = bp->prev;
- bp->prev->next = bp->next;
-
- bp->next = buf_head;
- bp->prev = END_OF_CHAIN;
- buf_head->prev = bp;
- buf_head = bp;
- }
- return (bp->data[ch_offset]);
- }
-
- /*
- * Determine if a specific block is currently in one of the buffers.
- */
- static int
- buffered(block)
- long block;
- {
- register struct buf *bp;
-
- for (bp = buf_head; bp != END_OF_CHAIN; bp = bp->next)
- if (bp->block == block)
- return (1);
- return (0);
- }
-
- /*
- * Seek to a specified position in the file.
- * Return 0 if successful, non-zero if can't seek there.
- */
- public int
- ch_seek(pos)
- register POSITION pos;
- {
- long new_block;
-
- new_block = pos / BUFSIZ;
- if (!ispipe || new_block == last_piped_block + 1 || buffered(new_block))
- {
- /*
- * Set read pointer.
- */
- ch_block = new_block;
- ch_offset = pos % BUFSIZ;
- return (0);
- }
- return (1);
- }
-
- /*
- * Seek to the end of the file.
- */
- public int
- ch_end_seek()
- {
- if (ispipe)
- {
- /*
- * Do it the slow way: read till end of data.
- */
- while (ch_forw_get() != EOF)
- ;
- } else
- {
- (void) ch_seek((POSITION)(lseek(file, (off_t)0, 2)));
- }
- return (0);
- }
-
- /*
- * Return the length of the file, if known.
- */
- public POSITION
- ch_length()
- {
- if (ispipe)
- return (ch_fsize);
- return ((POSITION)(lseek(file, (off_t)0, 2)));
- }
-
- /*
- * Return the current position in the file.
- */
- public POSITION
- ch_tell()
- {
- return (ch_block * BUFSIZ + ch_offset);
- }
-
- /*
- * Get the current char and post-increment the read pointer.
- */
- public int
- ch_forw_get()
- {
- register int c;
-
- c = ch_get();
- if (c != EOF && ++ch_offset >= BUFSIZ)
- {
- ch_offset = 0;
- ch_block ++;
- }
- return (c);
- }
-
- /*
- * Pre-decrement the read pointer and get the new current char.
- */
- public int
- ch_back_get()
- {
- register int c;
-
- if (--ch_offset < 0)
- {
- if (ch_block <= 0 || (ispipe && !buffered(ch_block-1)))
- {
- ch_offset = 0;
- return (EOF);
- }
- ch_offset = BUFSIZ - 1;
- ch_block--;
- }
- c = ch_get();
- return (c);
- }
-
- /*
- * Initialize the buffer pool to all empty.
- * Caller suggests that we use want_nbufs buffers.
- */
- public void
- ch_init(want_nbufs)
- int want_nbufs;
- {
- register struct buf *bp;
- char *calloc();
-
- if (nbufs < want_nbufs)
- {
- /*
- * We don't have enough buffers.
- * Free what we have (if any) and allocate some new ones.
- */
- if (bufs != NULL)
- free((char *)bufs);
- bufs = (struct buf *) calloc(want_nbufs, sizeof(struct buf));
- nbufs = want_nbufs;
- if (bufs == NULL)
- {
- /*
- * Couldn't get that many.
- * Try for a small default number of buffers.
- */
- char message[80];
- sprintf(message,
- "Cannot allocate %d buffers. Using %d buffers.",
- nbufs, DEF_NBUFS);
- error(message);
- bufs = (struct buf *) calloc(DEF_NBUFS, sizeof(struct buf));
- nbufs = DEF_NBUFS;
- if (bufs == NULL)
- {
- /*
- * Couldn't even get the smaller number of bufs.
- * Something is wrong here, don't continue.
- */
- sprintf(message,
- "Cannot even allocate %d buffers! Quitting.\n",
- DEF_NBUFS);
- error(message);
- quit();
- /*NOTREACHED*/
- }
- }
- }
-
- /*
- * Initialize the buffers to empty.
- * Set up the circular list.
- */
- for (bp = &bufs[0]; bp < &bufs[nbufs]; bp++)
- {
- bp->next = bp + 1;
- bp->prev = bp - 1;
- bp->block = (long)(-1);
- }
- bufs[0].prev = bufs[nbufs-1].next = END_OF_CHAIN;
- buf_head = &bufs[0];
- buf_tail = &bufs[nbufs-1];
- last_piped_block = -1;
- ch_fsize = NULL_POSITION;
- (void) ch_seek((POSITION)0);
- }
- SHAR_EOF
- fi
- if test -f 'command.c'
- then
- echo shar: "will not over-write existing file 'command.c'"
- else
- cat << \SHAR_EOF > 'command.c'
- /*
- * User-level command processor.
- */
-
- #include "less.h"
- #include "position.h"
- #include <setjmp.h>
-
- extern jmp_buf main_loop;
- extern int erase_char, kill_char;
- extern int pr_type;
- extern int sigs;
- extern int ispipe;
- extern int quit_at_eof;
- extern int hit_eof;
- extern int sc_width, sc_height;
- extern int sc_window;
- extern char *first_cmd;
- extern char version[];
- extern char current_file[];
- extern char *editor;
-
- static char cmdbuf[90]; /* Buffer for holding a multi-char command */
- static char *cp; /* Pointer into cmdbuf */
- static int cmd_col; /* Current column of the multi-char command */
- static char mcc; /* The multi-char command letter (e.g. '/') */
- static char last_mcc; /* The previous mcc */
-
- /*
- * Reset command buffer (to empty).
- */
- cmd_reset()
- {
- cp = cmdbuf;
- }
-
- /*
- * Backspace in command buffer.
- */
- static int
- cmd_erase()
- {
- if (cp == cmdbuf)
- /*
- * Backspace past beginning of the string:
- * this usually means abort the command.
- */
- return (1);
-
- if (control_char(*--cp))
- {
- /*
- * Erase an extra character, for the carat.
- */
- backspace();
- cmd_col--;
- }
- backspace();
- cmd_col--;
- return (0);
- }
-
- /*
- * Set up the display to start a new multi-character command.
- */
- start_mcc()
- {
- lower_left();
- clear_eol();
- putc(mcc);
- cmd_col = 1;
- }
-
- /*
- * Process a single character of a multi-character command, such as
- * a number, or the pattern of a search command.
- */
- static int
- cmd_char(c)
- int c;
- {
- if (c == erase_char)
- {
- if (cmd_erase())
- return (1);
- } else if (c == kill_char)
- {
- /* {{ Could do this faster, but who cares? }} */
- while (cmd_erase() == 0)
- ;
- } else
- {
- /*
- * Append the character to the string,
- * if there is room in the buffer and on the screen.
- */
- if (cp < &cmdbuf[sizeof(cmdbuf)-1] && cmd_col < sc_width-3)
- {
- *cp++ = c;
- if (control_char(c))
- {
- putc('^');
- cmd_col++;
- c = carat_char(c);
- }
- putc(c);
- cmd_col++;
- } else
- bell();
- }
- return (0);
- }
-
- /*
- * Return the number currently in the command buffer.
- */
- static int
- cmd_int()
- {
- *cp = '\0';
- cp = cmdbuf;
- return (atoi(cmdbuf));
- }
-
- /*
- * Move the cursor to lower left before executing a command.
- * This looks nicer if the command takes a long time before
- * updating the screen.
- */
- static void
- cmd_exec()
- {
- lower_left();
- flush();
- }
-
- /*
- * Display the appropriate prompt.
- */
- static void
- prompt()
- {
- register char *p;
-
- if (first_cmd != NULL && *first_cmd != '\0')
- /*
- * No prompt necessary if commands are from first_cmd
- * rather than from the user.
- */
- return;
-
- /*
- * Select the proper prompt and display it.
- */
- p = pr_string();
- if (p == NULL)
- putc(':');
- else
- {
- so_enter();
- puts(p);
- so_exit();
- }
- }
-
- /*
- * Get command character.
- * The character normally comes from the keyboard,
- * but may come from the "first_cmd" string.
- */
- static int
- getcc()
- {
- if (first_cmd == NULL)
- return (getc());
-
- if (*first_cmd == '\0')
- {
- /*
- * Reached end of first_cmd input.
- */
- first_cmd = NULL;
- if (cp > cmdbuf && position(TOP) == NULL_POSITION)
- {
- /*
- * Command is incomplete, so try to complete it.
- * There are only two cases:
- * 1. We have "/string" but no newline. Add the \n.
- * 2. We have a number but no command. Treat as #g.
- * (This is all pretty hokey.)
- */
- if (mcc != ':')
- return ('\n');
- else
- return ('g');
- }
- return (getc());
- }
- return (*first_cmd++);
- }
-
- /*
- * Main command processor.
- * Accept and execute commands until a quit command, then return.
- */
- public void
- commands()
- {
- register int c;
- register int n;
- register int scroll = 10;
-
- mcc = last_mcc = 0;
-
- setjmp(main_loop);
- for (;;)
- {
- /*
- * Display prompt and accept a character.
- */
- psignals(); /* See if any signals need processing */
-
- if (quit_at_eof && hit_eof > 1)
- /*
- * After hitting end-of-file for the second time,
- * automatically advance to the next file.
- * If there are no more files, quit.
- */
- next_file(1);
-
- cmd_reset();
- lower_left();
- clear_eol();
- prompt();
- c = getcc();
-
- again:
- if (sigs)
- continue;
-
- if (mcc)
- {
- /*
- * We are in a multi-character command.
- * All chars until newline go into the command buffer.
- * (Note that mcc == ':' is a special case that
- * means a number is being entered.)
- */
- if (mcc != ':' && (c == '\n' || c == '\r'))
- {
- /*
- * Execute the command.
- */
- *cp = '\0';
- cmd_exec();
- if (mcc == 'E')
- {
- char *p;
- /*
- * Ignore leading spaces
- * in the filename.
- */
- for (p = cmdbuf; *p == ' '; p++) ;
- edit(p);
- #if SHELL_ESCAPE
- } else if (mcc == '!')
- {
- lsystem(cmdbuf);
- error("!done");
- first_cmd = "r"; /* Repaint */
- #endif
- } else
- search(mcc, cmdbuf, n);
- mcc = 0;
- } else
- {
- if (mcc == ':' && (c < '0' || c > '9') &&
- c != erase_char && c != kill_char)
- {
- /*
- * This is not part of the number
- * we were entering. Process
- * it as a regular character.
- */
- mcc = 0;
- goto again;
- }
-
- /*
- * Append the char to the command buffer.
- */
- if (cmd_char(c))
- {
- /* Abort the multi-char command. */
- mcc = 0;
- continue;
- }
- c = getcc();
- goto again;
- }
- } else switch (c)
- {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- /*
- * First digit of a number.
- */
- mcc = ':';
- start_mcc();
- goto again;
-
- case 'f':
- case ' ':
- case CONTROL('F'):
- /*
- * Forward one screen.
- */
- n = cmd_int();
- if (n <= 0)
- n = sc_window;
- forward(n, 1);
- break;
-
- case 'b':
- case CONTROL('B'):
- /*
- * Backward one screen.
- */
- n = cmd_int();
- if (n <= 0)
- n = sc_window;
- backward(n, 1);
- break;
-
- case 'e':
- case 'j':
- case '\r':
- case '\n':
- case CONTROL('E'):
- /*
- * Forward N (default 1) line.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- forward(n, 0);
- break;
-
- case 'y':
- case 'k':
- case CONTROL('K'):
- case CONTROL('Y'):
- /*
- * Backward N (default 1) line.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- backward(n, 0);
- break;
-
- case 'd':
- case CONTROL('D'):
- /*
- * Forward N lines
- * (default same as last 'd' or 'u' command).
- */
- n = cmd_int();
- if (n > 0)
- scroll = n;
- forward(scroll, 0);
- break;
-
- case 'u':
- case CONTROL('U'):
- /*
- * Forward N lines
- * (default same as last 'd' or 'u' command).
- */
- n = cmd_int();
- if (n > 0)
- scroll = n;
- backward(scroll, 0);
- break;
-
- case 'R':
- /*
- * Flush buffers, then repaint screen.
- */
- ch_init(0);
- /* Fall thru */
- case 'r':
- case CONTROL('R'):
- case CONTROL('L'):
- /*
- * Repaint screen.
- */
- repaint();
- break;
-
- case 'g':
- /*
- * Go to line N, default beginning of file.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- cmd_exec();
- jump_back(n);
- break;
-
- case 'p':
- case '%':
- /*
- * Go to a specified percentage into the file.
- */
- n = cmd_int();
- if (n < 0)
- n = 0;
- if (n > 100)
- n = 100;
- cmd_exec();
- jump_percent(n);
- break;
-
- case 'G':
- /*
- * Go to line N, default end of file.
- */
- n = cmd_int();
- cmd_exec();
- if (n <= 0)
- jump_forw();
- else
- jump_back(n);
- break;
-
- case '=':
- case CONTROL('G'):
- /*
- * Print file name, etc.
- */
- error(eq_message());
- break;
-
- case 'V':
- /*
- * Print version number, without the "@(#)".
- */
- error(version+4);
- break;
-
- case 'q':
- /*
- * Exit.
- */
- return;
-
- case '/':
- case '?':
- /*
- * Search for a pattern.
- * Accept chars of the pattern until \n.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- mcc = last_mcc = c;
- start_mcc();
- c = getcc();
- goto again;
-
- case 'n':
- /*
- * Repeat previous search.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- mcc = last_mcc;
- start_mcc();
- cmd_exec();
- search(mcc, (char *)NULL, n);
- mcc = 0;
- break;
-
- case 'h':
- /*
- * Help.
- */
- help();
- repaint();
- break;
-
- case 'E':
- /*
- * Edit a new file. Get the filename.
- */
- cmd_reset();
- mcc = 'E';
- start_mcc();
- puts("dit: "); /* This looks nicer */
- cmd_col += 5;
- c = getcc();
- goto again;
-
- #if SHELL_ESCAPE
- case '!':
- /*
- * Shell escape.
- */
- cmd_reset();
- mcc = '!';
- start_mcc();
- c = getcc();
- goto again;
- #endif
-
- #if EDITOR
- case 'v':
- if (ispipe)
- {
- error("Cannot edit standard input");
- break;
- }
- sprintf(cmdbuf, "%s %s", editor, current_file);
- lsystem(cmdbuf);
- first_cmd = "R";
- break;
- #endif
-
- case 'N':
- /*
- * Examine next file.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- next_file(n);
- break;
-
- case 'P':
- /*
- * Examine previous file.
- */
- n = cmd_int();
- if (n <= 0)
- n = 1;
- prev_file(n);
- break;
-
- case '-':
- /*
- * Toggle a flag setting.
- */
- mcc = '-';
- start_mcc();
- c = getcc();
- mcc = 0;
- if (c == erase_char || c == kill_char)
- break;
- toggle_option(c);
- break;
-
- case 'm':
- /*
- * Set a mark.
- */
- lower_left();
- clear_eol();
- puts("mark: ");
- c = getcc();
- if (c == erase_char || c == kill_char)
- break;
- setmark(c);
- break;
-
- case '\'':
- /*
- * Go to a mark.
- */
- lower_left();
- clear_eol();
- puts("goto mark: ");
- c = getcc();
- if (c == erase_char || c == kill_char)
- break;
- gomark(c);
- break;
-
- default:
- bell();
- break;
- }
- }
- }
- SHAR_EOF
- fi
- if test -f 'funcs.h'
- then
- echo shar: "will not over-write existing file 'funcs.h'"
- else
- cat << \SHAR_EOF > 'funcs.h'
- public void edit ();
- public void next_file ();
- public void prev_file ();
- public void quit ();
- public void init_option ();
- public void toggle_option ();
- public void scan_option ();
- public void forward ();
- public void backward ();
- public void repaint ();
- public void jump_forw ();
- public void jump_back ();
- public void jump_percent ();
- public void jump_loc ();
- public void init_mark ();
- public void setmark ();
- public void gomark ();
- public void search ();
- public int ch_seek ();
- public int ch_end_seek ();
- public POSITION ch_length ();
- public POSITION ch_tell ();
- public int ch_forw_get ();
- public int ch_back_get ();
- public void ch_init ();
- public POSITION position ();
- public void add_forw_pos ();
- public void add_back_pos ();
- public void pos_clear ();
- public int onscreen ();
- public POSITION forw_line ();
- public POSITION back_line ();
- public void put_line ();
- public int control_char ();
- public int carat_char ();
- public void flush ();
- public void dropout ();
- public void putc ();
- public void puts ();
- public void error ();
- public int error_width ();
- public void raw_mode ();
- public void get_term ();
- public void init ();
- public void deinit ();
- public void home ();
- public void add_line ();
- public void lower_left ();
- public void bell ();
- public void vbell ();
- public void clear ();
- public void clear_eol ();
- public void so_enter ();
- public void so_exit ();
- public void ul_enter ();
- public void ul_exit ();
- public void backspace ();
- public void putbs ();
- public char * eq_message ();
- public char * pr_string ();
- public void prewind ();
- public int pappend ();
- public POSITION forw_raw_line ();
- public POSITION back_raw_line ();
- public void init_signals ();
- public void psignals ();
- public void lsystem ();
- public void help ();
- public void open_getc ();
- public int getc ();
- public void commands ();
- SHAR_EOF
- fi
- if test -f 'help.c'
- then
- echo shar: "will not over-write existing file 'help.c'"
- else
- cat << \SHAR_EOF > 'help.c'
- #include "less.h"
-
- /*
- * Display some help.
- * Help is in two pages.
- */
- static void
- help0()
- {
- puts("f, SPACE Forward one screen.\n");
- puts("b Backward one screen.\n");
- puts("e, j, CR * Forward N lines, default 1.\n");
- puts("y, k * Backward N lines, default 1.\n");
- puts("d * Forward N lines, default 10 or last N to d or u command.\n");
- puts("u * Backward N lines, default 10 or last N to d or u command.\n");
- puts("r Repaint screen.\n");
- puts("g * Go to line N, default 1.\n");
- puts("G * Like g, but default is last line in file.\n");
- puts("= Print current file name\n");
- puts("/pattern * Search forward for N-th occurence of pattern.\n");
- puts("?pattern * Search backward for N-th occurence of pattern.\n");
- puts("n * Repeat previous search (for N-th occurence).\n");
- puts("q Exit.\n");
- error("More help...");
- }
-
- static void
- help1()
- {
- char message[100];
- extern char all_options[];
-
- puts("R Repaint screen, discarding buffered input.\n");
- puts("p, % * Position to N percent into the file.\n");
- puts("m<letter> Mark the current position with <letter>.\n");
- puts("'<letter> Return to a previously marked position.\n");
- sprintf(message,
- "-X Toggle a flag (X may be one of \"%s\").\n",
- all_options);
- puts(message);
- puts("E [file] Examine a new file.\n");
- puts("N Examine the next file (from the command line).\n");
- puts("P Examine the previous file (from the command line).\n");
- puts("V Print version number.\n");
- #if SHELL_ESCAPE
- puts("!command Passes the command to a shell to be executed.\n");
- #endif
- #if EDITOR
- sprintf(message,
- "v Edit the current file with $EDITOR (default %s).\n",
- EDIT_PGM);
- puts(message);
- #endif
- error("");
- }
-
- public void
- help()
- {
- register int i;
-
- for (i = 0; i < 2; i++)
- {
- clear();
- puts("Commands marked with * may be preceeded by a number, N.\n\n");
-
- switch (i)
- {
- case 0: help0(); break;
- case 1: help1(); break;
- }
- }
- }
- SHAR_EOF
- fi
- if test -f 'input.c'
- then
- echo shar: "will not over-write existing file 'input.c'"
- else
- cat << \SHAR_EOF > 'input.c'
- /*
- * High level routines dealing with getting lines of input
- * from the file being viewed.
- *
- * When we speak of "lines" here, we mean PRINTABLE lines;
- * lines processed with respect to the screen width.
- * We use the term "raw line" to refer to lines simply
- * delimited by newlines; not processed with respect to screen width.
- */
-
- #include "less.h"
-
- extern int do_bs;
- extern int squeeze;
- extern char *line;
-
- /*
- * Get the next line.
- * A "current" position is passed and a "new" position is returned.
- * The current position is the position of the first character of
- * a line. The new position is the position of the first character
- * of the NEXT line. The line obtained is the line starting at curr_pos.
- */
- public POSITION
- forw_line(curr_pos)
- POSITION curr_pos;
- {
- POSITION new_pos;
- register int c;
-
- if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
- return (NULL_POSITION);
-
- c = ch_forw_get();
- if (c == EOF)
- return (NULL_POSITION);
-
- prewind();
- for (;;)
- {
- if (c == '\n' || c == EOF)
- {
- /*
- * End of the line.
- */
- new_pos = ch_tell();
- break;
- }
-
- /*
- * Append the char to the line and get the next char.
- */
- if (pappend(c))
- {
- /*
- * The char won't fit in the line; the line
- * is too long to print in the screen width.
- * End the line here.
- */
- new_pos = ch_tell() - 1;
- break;
- }
- c = ch_forw_get();
- }
- (void) pappend('\0');
-
- if (squeeze && *line == '\0')
- {
- /*
- * This line is blank.
- * Skip down to the last contiguous blank line
- * and pretend it is the one which we are returning.
- */
- while ((c = ch_forw_get()) == '\n')
- ;
- if (c != EOF)
- (void) ch_back_get();
- new_pos = ch_tell();
- }
-
- return (new_pos);
- }
-
- /*
- * Get the previous line.
- * A "current" position is passed and a "new" position is returned.
- * The current position is the position of the first character of
- * a line. The new position is the position of the first character
- * of the PREVIOUS line. The line obtained is the one starting at new_pos.
- */
- public POSITION
- back_line(curr_pos)
- POSITION curr_pos;
- {
- POSITION new_pos, begin_new_pos;
- int c;
-
- if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
- ch_seek(curr_pos-1))
- return (NULL_POSITION);
-
- if (squeeze)
- {
- /*
- * Find out if the "current" line was blank.
- */
- (void) ch_forw_get(); /* Skip the newline */
- c = ch_forw_get(); /* First char of "current" line */
- (void) ch_back_get(); /* Restore our position */
- (void) ch_back_get();
-
- if (c == '\n')
- {
- /*
- * The "current" line was blank.
- * Skip over any preceeding blank lines,
- * since we skipped them in forw_line().
- */
- while ((c = ch_back_get()) == '\n')
- ;
- if (c == EOF)
- return (NULL_POSITION);
- (void) ch_forw_get();
- }
- }
-
- /*
- * Scan backwards until we hit the beginning of the line.
- */
- for (;;)
- {
- c = ch_back_get();
- if (c == '\n')
- {
- /*
- * This is the newline ending the previous line.
- * We have hit the beginning of the line.
- */
- new_pos = ch_tell() + 1;
- break;
- }
- if (c == EOF)
- {
- /*
- * We have hit the beginning of the file.
- * This must be the first line in the file.
- * This must, of course, be the beginning of the line.
- */
- new_pos = (POSITION)0;
- break;
- }
- }
-
- /*
- * Now scan forwards from the beginning of this line.
- * We keep discarding "printable lines" (based on screen width)
- * until we reach the curr_pos.
- *
- * {{ This algorithm is pretty inefficient if the lines
- * are much longer than the screen width,
- * but I don't know of any better way. }}
- */
- if (ch_seek(new_pos))
- return (NULL_POSITION);
- loop:
- begin_new_pos = new_pos;
- prewind();
-
- do
- {
- c = ch_forw_get();
- new_pos++;
- if (c == '\n')
- break;
- if (pappend(c))
- {
- /*
- * Got a full printable line, but we haven't
- * reached our curr_pos yet. Discard the line
- * and start a new one.
- */
- (void) pappend('\0');
- (void) ch_back_get();
- new_pos--;
- goto loop;
- }
- } while (new_pos < curr_pos);
-
- (void) pappend('\0');
-
- return (begin_new_pos);
- }
- SHAR_EOF
- fi
- if test -f 'less.h'
- then
- echo shar: "will not over-write existing file 'less.h'"
- else
- cat << \SHAR_EOF > 'less.h'
- /*
- * Standard include file for "less".
- */
-
- /*
- * Language details.
- */
- #if !VOID
- #define void int
- #endif
- #define public /* PUBLIC FUNCTION */
-
- /*
- * Special types and constants.
- */
- typedef long POSITION;
- /*
- * {{ Warning: if POSITION is changed to other than "long",
- * you may have to change some of the printfs which use "%ld"
- * to print a variable of type POSITION. }}
- */
-
- #define END_POSITION ((POSITION)(-2))
- #define NULL_POSITION ((POSITION)(-1))
-
- #define EOF (0)
- #define NULL (0)
-
- /* How quiet should we be? */
- #define NOT_QUIET 0 /* Ring bell at eof and for errors */
- #define LITTLE_QUIET 1 /* Ring bell only for errors */
- #define VERY_QUIET 2 /* Never ring bell */
-
- /* How should we prompt? */
- #define PR_SHORT 0 /* Prompt with colon */
- #define PR_MEDIUM 1 /* Prompt with message */
- #define PR_LONG 2 /* Prompt with longer message */
-
- /* How should we handle backspaces? */
- #define BS_SPECIAL 0 /* Do special things for underlining and bold */
- #define BS_NORMAL 1 /* \b treated as normal char; actually output */
- #define BS_CONTROL 2 /* \b treated as control char; prints as ^H */
-
- /* Flag to eq_message() telling what to put in the message */
- #define MNAME 001 /* File name */
- #define MOF 002 /* "file x of y" */
- #define MBYTE 004 /* "byte x/y" */
- #define MPCT 010 /* Percentage into the file */
-
- /* Special chars used to tell put_line() to do something special */
- #define UL_CHAR '\201' /* Enter underline mode */
- #define UE_CHAR '\202' /* Exit underline mode */
- #define BO_CHAR '\203' /* Enter boldface mode */
- #define BE_CHAR '\204' /* Exit boldface mode */
-
- #define CONTROL(c) ((c)&037)
- #define SIGNAL(sig,func) signal(sig,func)
-
- off_t lseek();
-
- #include "funcs.h"
- SHAR_EOF
- fi
- if test -f 'less.l'
- then
- echo shar: "will not over-write existing file 'less.l'"
- else
- cat << \SHAR_EOF > 'less.l'
- .TH LESS l
- .SH NAME
- less \- opposite of more
- .SH SYNOPSIS
- .B "less [\-cdepstwmMqQuU] [\-h\fIn\fB] [\-b[fp]\fIn\fB] [\-x\fIn\fB] [\-[z]\fIn\fB] [+\fIcmd\fB] [\fIname\fB] ..."
- .SH DESCRIPTION
- \fILess\fR is a program similar to \fImore\fR(1), but which allows backwards
- movement in the file as well as forward movement. Also, \fIless\fR does not
- have to read the entire input file before starting, so with large input
- files it starts up faster than text editors like \fIvi\fR(1). \fILess\fR
- uses termcap, so it can run on a variety of terminals. There is even
- limited support for hardcopy terminals. (On a hardcopy terminal, lines
- which should be printed at the top of the screen are prefixed with an
- up-arrow.)
- .PP
- Commands are based on both \fImore\fR and \fIvi\fR. Commands may be
- preceeded by a decimal number, called N in the descriptions below. The
- number is used by some commands, as indicated.
- .SH COMMANDS
- .IP \fBh\fR
- Help: display a summary of these commands. If you forget all the other
- commands, remember this one.
- .PP
- .IP \fBSPACE\fR
- Scroll forward N lines, default one window (see option \fB\-z\fR below). If
- N is more than the screen size, only one screenful is displayed.
- .PP
- .IP \fBf\fR
- Same as \fBSPACE\fR.
- .PP
- .IP \fBb\fR
- Scroll backward N lines, default one window (see option \fB\-z\fR below).
- If N is more than the screen size, only one screenful is displayed.
- .PP
- .IP \fBRETURN\fR
- Scroll forward N lines, default 1. If N is more than the screen size, the
- entire N lines are displayed.
- .PP
- .IP \fBe\fR
- Same as \fBRETURN\fR.
- .PP
- .IP \fBj\fR
- Also the same as \fBRETURN\fR.
- .PP
- .IP \fBy\fR
- Scroll backward N lines, default 1. If N is more than the screen size, the
- entire N lines are displayed.
- .IP \fBk\fR
- Same as \fBy\fR.
- .PP
- .IP \fBd\fR
- Scroll forward N lines, default 10. If N is specified, it becomes the new
- default for all \fBd\fR and \fBu\fR commands.
- .PP
- .IP \fBu\fR
- Scroll backward N lines, default 10. If N is specified, it becomes the new
- default for all \fBd\fR and \fBu\fR commands.
- .PP
- .IP \fBr\fR
- Repaint the screen.
- .PP
- .IP \fBR\fR
- Repaint the screen, discarding any buffered input. Useful if the file is
- changing while it is being viewed.
- .PP
- .IP \fBg\fR
- Go to line N in the file, default 1 (beginning of file). (Warning: this may
- be slow if N is large.)
- .PP
- .IP \fBG\fR
- Go to line N in the file, default the end of the file. (Warning: this may
- be slow if standard input, rather than a file, is being read.)
- .PP
- .IP \fBp\fR
- Go to a position N percent into the file. N should be between 0 and 100.
- (This is possible if standard input is being read, but only if \fIless\fR
- has already read to the end of the file. It is always fast, but not always
- useful.)
- .PP
- .IP \fB%\fR
- Same as \fBp\fR.
- .PP
- .IP \fBm\fIl\fR
- Followed by any lowercase letter, \fIl\fR, marks the current position with
- that letter.
- .PP
- .IP \fB'\fIl\fR
- Followed by any lowercase letter, \fIl\fR, returns to the position which was
- previously marked with that letter. All marks are lost when a new file is
- examined.
- .PP
- .IP \fB/pattern\fR
- Search forward in the file for the N-th occurence of the \fIpattern\fR. N
- defaults to 1. The \fIpattern\fR is a regular expression, as recognized by
- \fIed\fR. The search starts at the second line displayed (but see the
- \fB\-t\fR option, which changes this).
- .PP
- .IP \fB?pattern\fR
- Search backward in the file for the N-th occurence of the \fIpattern\fR.
- The search starts at the line immediately before the top line displayed.
- .PP
- .IP \fBn\fR
- Repeat previous search, for N-th occurence of the last \fIpattern\fR.
- .PP
- .IP \fBE\fR\ \fI[filename]\fR
- Examine a new file. If the \fIfilename\fR is missing, the "current" file
- (see the \fBN\fR and \fBP\fR commands below) from the list of files in the
- command line is re-examined.
- .PP
- .IP \fBN\fR
- Examine the next file (from the list of files given in the command line).
- If a number N is specified (not to be confused with the command \fBN\fR),
- the N-th next file is examined.
- .PP
- .IP \fBP\fR
- Examine the previous file. If a number N is specified, the N-th previous
- file is examined.
- .PP
- .IP \fB=\fR
- Prints the name of the file being viewed and the byte offset of the bottom
- line being displayed. If possible, it also prints the length of the file
- and the percent of the file above the last displayed line.
- .PP
- .IP \fB\-\fR
- Followed by one of the command line option letters (see below), this will
- toggle the setting of that option and print a message describing the new
- setting.
- .PP
- .IP \fBV\fR
- Prints the version number of \fIless\fR being run.
- .PP
- .IP \fBq\fR
- Exits \fIless\fR.
- .PP
- The following two commands may or may not be valid, depending on your
- particular installation.
- .PP
- .IP \fBv\fR
- Invokes an editor to edit the current file being viewed. The editor is
- taken from the environment variable \fBEDITOR\fR, or defaults to \fIvi\fR.
- .PP
- .IP \fB!\fR\ \fIshell-command\fR
- Invokes a shell to run the
- .I shell-command
- given.
- .PP
- .SH OPTIONS
- Command line options are described below. Options are also taken from the
- environment variable \fBLESS\fR. (The environment variable is parsed before
- the command line, so command line options override the \fBLESS\fR environment
- variable. Options may be changed while \fIless\fR is running via the
- \fB"\-"\fR command.) For example, if you like more-style prompting, to
- avoid typing \fBless\ \-m\ ...\fR each time \fIless\fR is invoked, you might
- tell \fIcsh\fR:
- .sp
- .B setenv LESS m
- .sp
- or if you use \fIsh\fR:
- .sp
- .B LESS=m; export LESS
- .IP \fB\-s\fR
- The \fB\-s\fR flag causes consecutive blank lines to be squeezed into a
- single blank line. This is useful when viewing \fInroff\fR output.
- .IP \fB\-t\fR
- Normally, forward searches start just after the top displayed line (that is,
- at the second displayed line). Thus forward searches include the currently
- displayed screen. The \fB\-t\fR command line option causes forward searches
- to start just after the bottom line displayed, thus skipping the currently
- displayed screen.
- .IP \fB\-m\fR
- Normally, \fIless\fR prompts with a colon. The \fB\-m\fR command line
- option causes \fIless\fR to prompt verbosely like \fImore\fR, printing the
- file name and percent into the file.
- .IP \fB\-M\fR
- The \fB\-M\fR command line option causes \fIless\fR to prompt even more
- verbosely than \fImore\fR.
- .IP \fB\-q\fR
- Normally, if an attempt is made to scroll past the end of the file or before
- the beginning of the file, the terminal bell is rung to indicate this fact.
- The \fB\-q\fR command line option tells \fIless\fR not to ring the bell at
- such times. If the terminal has a "visual bell", it is used instead.
- .IP \fB\-Q\fR
- Even if \fB\-q\fR is given, \fIless\fR will ring the bell on certain other
- errors, such as typing an invalid character. The \fB\-Q\fR command line
- option tells \fIless\fR to be quiet all the time; that is, never ring the
- terminal bell. If the terminal has a "visual bell", it is used instead.
- .IP \fB\-e\fR
- Normally the only way to exit less is via the "q" command. The \fB\-e\fR
- command line option tells less to automatically exit the second time it
- reaches end-of-file.
- .IP \fB\-u\fR
- If the \fB\-u\fR command line option is given, backspaces are treated as
- printable characters; that is, they are sent to the terminal when they
- appear in the input.
- .IP \fB\-U\fR
- If the \fB\-U\fR command line option is given, backspaces are printed as the
- two character sequence "^H". If neither \fB\-u\fR nor \fB\-U\fR is given,
- backspaces which appear adjacent to an underscore character or sequences of
- a character interleaved with backspaces are treated specially: the
- underlined or boldfaced text is displayed using the terminal's hardware
- capability. Note that the \fB\-v\fR option below superceeds both \fB\-u\fR
- and \fB\-U\fR.
- .IP \fB\-w\fR
- Normally, \fIless\fR uses a tilde character to represent lines past the end
- of the file. The \fB\-w\fR option causes blank lines to be used instead.
- .IP \fB\-d\fR
- Normally, \fIless\fR will complain if the terminal is dumb; that is, lacks
- some important capability, such as the ability to clear the screen or scroll
- backwards. The \fB\-d\fR flag suppresses this complaint (but does not
- otherwise change the behavior of the program on a dumb terminal).
- .IP \fB\-p\fR
- Normally, \fIless\fR will repaint the screen by scrolling from the bottom of
- the screen. If the \fB\-p\fR flag is set, when \fIless\fR needs to change
- the entire display, it will clear the screen and paint from the top line
- down.
- .IP \fB\-h\fIn\fR
- Normally, \fIless\fR will scroll backwards when backwards movement is
- necessary. The \fB\-h\fR option specifies a maximum number of lines to
- scroll backwards. If it is necessary to move backwards more than this many
- lines, the screen is repainted in a forward direction. (If the terminal
- does not have the ability to scroll backwards, \fB\-h\fI0\fR is implied.)
- .IP \fB\-[z]\fIn\fR
- When given a backwards or forwards window command, \fIless\fR will by
- default scroll backwards or forwards one screenful of lines. The \fB\-z\fR
- option changes the default scrolling window size to \fIn\fR lines. If
- \fIn\fR is greater than the screen size, the scrolling window size will be
- set to one screenful. Note that the \fBz\fR is optional for compatibility
- with more.
- .IP \fB\-x\fR
- The \fB\-x\fR command line option sets tab stops every \fIn\fR positions.
- The default for \fIn\fR is 8.
- .IP \fB\-b[fp]\fIn\fR
- The \fB\-b\fR command line option tells \fIless\fR to use a non-standard
- buffer size. There are two standard (default) buffer sizes, one is used
- when a file is being read and the other when a pipe (standard input) is
- being read. The current defaults are 5 buffers for files and 12 for pipes.
- (Buffers are 1024 bytes.) The number \fIn\fR specifies a different number
- of buffers to use. The \fB\-b\fR may be followed by \fBf\fR, in which case
- only the file default is changed, or by \fBp\fR in which case only the pipe
- default is changed. Otherwise, both are changed.
- .IP \fB\-c\fR
- Normally, when data is read by \fIless\fR, it is scanned to ensure that bit
- 7 (the high order bit) is turned off in each byte read, and to ensure that
- there are no null (zero) bytes in the data (null bytes are turned into "@"
- characters). If the data is known to be "clean", the \fB\-c\fR command line
- option will tell \fIless\fR to skip this checking, causing an imperceptible
- speed improvement. (However, if the data is not "clean", unpredicatable
- results may occur.)
- .IP \fB\-v\fR
- The \fB\-v\fR option tells less to print non-printing characters in a
- visible way ala \fIcat\fR(1). Control characters are printed as ^X (the
- delete character (octal 0177) is printed as ^?). Characters with the 0200
- bit set are printed as M- followed by the character represented by the low
- order seven bits.
- .IP \fB+\fIcommand\fR
- If a command line option begins with \fB+\fR, the remainder of that option
- is taken to be an initial command to \fIless\fR. For example, \fB+\fIG\fR
- tells \fIless\fR to start at the end of the file rather than the beginning,
- and \fB+\fI/xyz\fR tells it to start at the first occurence of \fIxyz\fR in
- the file. As a special case, \fB+\fI<number>\fR acts like
- \fB+\fI<number>g\fR; that is, it starts the display at the specified line
- number (however, see the caveat under the \fBg\fR command above). If the
- option starts with \fB++\fR, the initial command applies to every file being
- viewed, not just the first one.
- .SH BUGS
- When used on standard input (rather than a file), you can move backwards
- only a finite amount, corresponding to that portion of the file which is
- still buffered.
- SHAR_EOF
- fi
- if test -f 'line.c'
- then
- echo shar: "will not over-write existing file 'line.c'"
- else
- cat << \SHAR_EOF > 'line.c'
- /*
- * Routines to manipulate the "line buffer".
- * The line buffer holds a line of output as it is being built
- * in preparation for output to the screen.
- * We keep track of the PRINTABLE length of the line as it is being built.
- */
-
- #include "less.h"
-
- static char linebuf[1024]; /* Buffer which holds the current output line */
- static char *curr; /* Pointer into linebuf */
- static int column; /* Printable length, accounting for
- backspaces, etc. */
- /*
- * A ridiculously complex state machine takes care of backspaces
- * when in BS_SPECIAL mode. The complexity arises from the attempt
- * to deal with all cases, especially involving long lines with underlining,
- * boldfacing or whatever. There are still some cases which will break it.
- *
- * There are four states:
- * LN_NORMAL is the normal state (not in underline mode).
- * LN_UNDERLINE means we are in underline mode. We expect to get
- * either a sequence like "_\bX" or "X\b_" to continue
- * underline mode, or anything else to end underline mode.
- * LN_BOLDFACE means we are in boldface mode. We expect to get sequences
- * like "X\bX\b...X\bX" to continue boldface mode, or anything
- * else to end boldface mode.
- * LN_UL_X means we are one character after LN_UNDERLINE
- * (we have gotten the '_' in "_\bX" or the 'X' in "X\b_").
- * LN_UL_XB means we are one character after LN_UL_X
- * (we have gotten the backspace in "_\bX" or "X\b_";
- * we expect one more ordinary character,
- * which will put us back in state LN_UNDERLINE).
- * LN_BO_X means we are one character after LN_BOLDFACE
- * (we have gotten the 'X' in "X\bX").
- * LN_BO_XB means we are one character after LN_BO_X
- * (we have gotten the backspace in "X\bX";
- * we expect one more 'X' which will put us back
- * in LN_BOLDFACE).
- */
- static int ln_state; /* Currently in normal/underline/bold/etc mode? */
- #define LN_NORMAL 0 /* Not in underline, boldface or whatever mode */
- #define LN_UNDERLINE 1 /* In underline, need next char */
- #define LN_UL_X 2 /* In underline, got char, need \b */
- #define LN_UL_XB 3 /* In underline, got char & \b, need one more */
- #define LN_BOLDFACE 4 /* In boldface, need next char */
- #define LN_BO_X 5 /* In boldface, got char, need \b */
- #define LN_BO_XB 6 /* In boldface, got char & \b, need same char */
-
- public char *line; /* Pointer to the current line.
- Usually points to linebuf. */
-
- extern int bs_mode;
- extern int tabstop;
- extern int bo_width, be_width;
- extern int ul_width, ue_width;
- extern int sc_width, sc_height;
-
- /*
- * Rewind the line buffer.
- */
- public void
- prewind()
- {
- line = curr = linebuf;
- ln_state = LN_NORMAL;
- column = 0;
- }
-
- /*
- * Append a character to the line buffer.
- * Expand tabs into spaces, handle underlining, boldfacing, etc.
- * Returns 0 if ok, 1 if couldn't fit in buffer.
- */
-
- #define NEW_COLUMN(newcol) if ((newcol) + ((ln_state)?ue_width:0) > sc_width) \
- return (1); else column = (newcol)
-
- public int
- pappend(c)
- int c;
- {
- if (c == '\0')
- {
- /*
- * Terminate any special modes, if necessary.
- * Append a '\0' to the end of the line.
- */
- switch (ln_state)
- {
- case LN_UL_X:
- curr[0] = curr[-1];
- curr[-1] = UE_CHAR;
- curr++;
- break;
- case LN_BO_X:
- curr[0] = curr[-1];
- curr[-1] = BE_CHAR;
- curr++;
- break;
- case LN_UL_XB:
- case LN_UNDERLINE:
- *curr++ = UE_CHAR;
- break;
- case LN_BO_XB:
- case LN_BOLDFACE:
- *curr++ = BE_CHAR;
- break;
- }
- ln_state = LN_NORMAL;
- *curr = '\0';
- return (0);
- }
-
- if (curr > linebuf + sizeof(linebuf) - 12)
- /*
- * Almost out of room in the line buffer.
- * Don't take any chances.
- * {{ Linebuf is supposed to be big enough that this
- * will never happen, but may need to be made
- * bigger for wide screens or lots of backspaces. }}
- */
- return (1);
-
- if (bs_mode == BS_SPECIAL)
- {
- /*
- * Advance the state machine.
- */
- switch (ln_state)
- {
- case LN_NORMAL:
- if (curr <= linebuf + 1 || curr[-1] != '\b')
- break;
-
- if (c == curr[-2])
- goto enter_boldface;
- if (c == '_' || curr[-2] == '_')
- goto enter_underline;
- curr -= 2;
- break;
-
- enter_boldface:
- /*
- * We have "X\bX" (including the current char).
- * Switch into boldface mode.
- */
- if (column + bo_width + be_width + 1 >= sc_width)
- /*
- * Not enough room left on the screen to
- * enter and exit boldface mode.
- */
- return (1);
-
- if (bo_width > 0 &&
- curr > linebuf + 2 && curr[-3] == ' ')
- {
- /*
- * Special case for magic cookie terminals:
- * if the previous char was a space, replace
- * it with the "enter boldface" sequence.
- */
- curr[-3] = BO_CHAR;
- column += bo_width-1;
- } else
- {
- curr[-1] = curr[-2];
- curr[-2] = BO_CHAR;
- column += bo_width;
- curr++;
- }
- goto ln_bo_xb_case;
-
- enter_underline:
- /*
- * We have either "_\bX" or "X\b_" (including
- * the current char). Switch into underline mode.
- */
- if (column + ul_width + ue_width + 1 >= sc_width)
- /*
- * Not enough room left on the screen to
- * enter and exit underline mode.
- */
- return (1);
-
- if (ul_width > 0 &&
- curr > linebuf + 2 && curr[-3] == ' ')
- {
- /*
- * Special case for magic cookie terminals:
- * if the previous char was a space, replace
- * it with the "enter underline" sequence.
- */
- curr[-3] = UL_CHAR;
- column += ul_width-1;
- } else
- {
- curr[-1] = curr[-2];
- curr[-2] = UL_CHAR;
- column += ul_width;
- curr++;
- }
- goto ln_ul_xb_case;
- /*NOTREACHED*/
- case LN_UL_XB:
- /*
- * Termination of a sequence "_\bX" or "X\b_".
- */
- if (c != '_' && curr[-2] != '_' && c == curr[-2])
- {
- /*
- * We seem to have run on from underlining
- * into boldfacing - this is a nasty fix, but
- * until this whole routine is rewritten as a
- * real DFA, ... well ...
- */
- curr[0] = curr[-2];
- curr[-2] = UE_CHAR;
- curr[-1] = BO_CHAR;
- curr += 2; /* char & non-existent backspace */
- ln_state = LN_BO_XB;
- goto ln_bo_xb_case;
- }
- ln_ul_xb_case:
- if (c == '_')
- c = curr[-2];
- curr -= 2;
- ln_state = LN_UNDERLINE;
- break;
- case LN_BO_XB:
- /*
- * Termination of a sequnce "X\bX".
- */
- if (c != curr[-2] && (c == '_' || curr[-2] == '_'))
- {
- /*
- * We seem to have run on from
- * boldfacing into underlining.
- */
- curr[0] = curr[-2];
- curr[-2] = BE_CHAR;
- curr[-1] = UL_CHAR;
- curr += 2; /* char & non-existent backspace */
- ln_state = LN_UL_XB;
- goto ln_ul_xb_case;
- }
- ln_bo_xb_case:
- curr -= 2;
- ln_state = LN_BOLDFACE;
- break;
- case LN_UNDERLINE:
- if (column + ue_width + bo_width + 1 + be_width >= sc_width)
- /*
- * We have just barely enough room to
- * exit underline mode and handle a possible
- * underline/boldface run on mixup.
- */
- return (1);
- ln_state = LN_UL_X;
- break;
- case LN_BOLDFACE:
- if (c == '\b')
- {
- ln_state = LN_BO_XB;
- break;
- }
- if (column + be_width + ul_width + 1 + ue_width >= sc_width)
- /*
- * We have just barely enough room to
- * exit underline mode and handle a possible
- * underline/boldface run on mixup.
- */
- return (1);
- ln_state = LN_BO_X;
- break;
- case LN_UL_X:
- if (c == '\b')
- ln_state = LN_UL_XB;
- else
- {
- /*
- * Exit underline mode.
- * We have to shuffle the chars a bit
- * to make this work.
- */
- curr[0] = curr[-1];
- curr[-1] = UE_CHAR;
- column += ue_width;
- if (ue_width > 0 && curr[0] == ' ')
- /*
- * Another special case for magic
- * cookie terminals: if the next
- * char is a space, replace it
- * with the "exit underline" sequence.
- */
- column--;
- else
- curr++;
- ln_state = LN_NORMAL;
- }
- break;
- case LN_BO_X:
- if (c == '\b')
- ln_state = LN_BO_XB;
- else
- {
- /*
- * Exit boldface mode.
- * We have to shuffle the chars a bit
- * to make this work.
- */
- curr[0] = curr[-1];
- curr[-1] = BE_CHAR;
- column += be_width;
- if (be_width > 0 && curr[0] == ' ')
- /*
- * Another special case for magic
- * cookie terminals: if the next
- * char is a space, replace it
- * with the "exit boldface" sequence.
- */
- column--;
- else
- curr++;
- ln_state = LN_NORMAL;
- }
- break;
- }
- }
-
- if (c == '\t')
- {
- /*
- * Expand a tab into spaces.
- */
- do
- {
- NEW_COLUMN(column+1);
- } while ((column % tabstop) != 0);
- *curr++ = '\t';
- return (0);
- }
-
- if (c == '\b')
- {
- if (bs_mode == BS_CONTROL)
- {
- /*
- * Treat backspace as a control char: output "^H".
- */
- NEW_COLUMN(column+2);
- *curr++ = ('H' | 0200);
- } else
- {
- /*
- * Output a real backspace.
- */
- column--;
- *curr++ = '\b';
- }
- return (0);
- }
-
- if (control_char(c))
- {
- /*
- * Put a "^X" into the buffer.
- * The 0200 bit is used to tell put_line() to prefix
- * the char with a ^. We don't actually put the ^
- * in the buffer because we sometimes need to move
- * chars around, and such movement might separate
- * the ^ from its following character.
- */
- NEW_COLUMN(column+2);
- *curr++ = (carat_char(c) | 0200);
- return (0);
- }
-
- /*
- * Ordinary character. Just put it in the buffer.
- */
- NEW_COLUMN(column+1);
- *curr++ = c;
- return (0);
- }
-
- /*
- * Analogous to forw_line(), but deals with "raw lines":
- * lines which are not split for screen width.
- * {{ This is supposed to be more efficient than forw_line(). }}
- */
- public POSITION
- forw_raw_line(curr_pos)
- POSITION curr_pos;
- {
- register char *p;
- register int c;
- POSITION new_pos;
-
- if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||
- (c = ch_forw_get()) == EOF)
- return (NULL_POSITION);
-
- p = linebuf;
-
- for (;;)
- {
- if (c == '\n' || c == EOF)
- {
- new_pos = ch_tell();
- break;
- }
- if (p >= &linebuf[sizeof(linebuf)-1])
- {
- /*
- * Overflowed the input buffer.
- * Pretend the line ended here.
- * {{ The line buffer is supposed to be big
- * enough that this never happens. }}
- */
- new_pos = ch_tell() - 1;
- break;
- }
- *p++ = c;
- c = ch_forw_get();
- }
- *p = '\0';
- line = linebuf;
- return (new_pos);
- }
-
- /*
- * Analogous to back_line(), but deals with "raw lines".
- * {{ This is supposed to be more efficient than back_line(). }}
- */
- public POSITION
- back_raw_line(curr_pos)
- POSITION curr_pos;
- {
- register char *p;
- register int c;
- POSITION new_pos;
-
- if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
- ch_seek(curr_pos-1))
- return (NULL_POSITION);
-
- p = &linebuf[sizeof(linebuf)];
- *--p = '\0';
-
- for (;;)
- {
- c = ch_back_get();
- if (c == '\n')
- {
- /*
- * This is the newline ending the previous line.
- * We have hit the beginning of the line.
- */
- new_pos = ch_tell() + 1;
- break;
- }
- if (c == EOF)
- {
- /*
- * We have hit the beginning of the file.
- * This must be the first line in the file.
- * This must, of course, be the beginning of the line.
- */
- new_pos = (POSITION)0;
- break;
- }
- if (p <= linebuf)
- {
- /*
- * Overflowed the input buffer.
- * Pretend the line ended here.
- */
- new_pos = ch_tell() + 1;
- break;
- }
- *--p = c;
- }
- line = p;
- return (new_pos);
- }
- SHAR_EOF
- fi
- if test -f 'main.c'
- then
- echo shar: "will not over-write existing file 'main.c'"
- else
- cat << \SHAR_EOF > 'main.c'
- /*
- * Entry point, initialization, miscellaneous routines.
- */
-
- #include "less.h"
- #include "position.h"
- #include <setjmp.h>
-
- public int ispipe;
- public jmp_buf main_loop;
- public char * first_cmd;
- public char * every_first_cmd;
- public int new_file;
- public int is_tty;
- public char current_file[128];
- public int ac;
- public char **av;
- public int curr_ac;
- #if EDITOR
- public char * editor;
- #endif
-
- extern int file;
- extern int nbufs;
- extern int sigs;
- extern int quit_at_eof;
- extern int p_nbufs, f_nbufs;
- extern int back_scroll;
- extern int top_scroll;
- extern int sc_height;
-
-
- /*
- * Edit a new file.
- * Filename "-" means standard input.
- * No filename means the "current" file, from the command line.
- */
- public void
- edit(filename)
- char *filename;
- {
- register int f;
- char message[100];
- static int any_edited = 0;
- static int hold_scroll = 0;
-
- if (filename == NULL || *filename == '\0')
- {
- if (curr_ac >= ac)
- {
- error("No current file");
- return;
- }
- filename = av[curr_ac];
- }
- if (strcmp(filename, "-") == 0)
- f = 0; /* Standard input */
- else if ((f = open(filename, 0)) < 0)
- {
- sprintf(message, "Cannot open %.*s",
- error_width()-13, filename);
- if (any_edited)
- error(message);
- else
- {
- puts(message);
- hold_scroll = 1;
- }
- return;
- }
-
- if (isatty(f))
- {
- /*
- * Not really necessary to call this an error,
- * but if the control terminal (for commands)
- * and the input file (for data) are the same,
- * we get weird results at best.
- */
- error("Can't take input from a terminal");
- if (f > 0)
- close(f);
- return;
- }
-
- /*
- * Close the current input file and set up to use the new one.
- */
- if (file > 0)
- close(file);
- new_file = 1;
- strcpy(current_file, filename);
- ispipe = (f == 0);
- file = f;
- ch_init( (ispipe) ? p_nbufs : f_nbufs );
- init_mark();
- if (every_first_cmd != NULL)
- first_cmd = every_first_cmd;
- if (is_tty)
- {
- any_edited = 1;
- if (hold_scroll)
- {
- /*
- * Before erasing the screen contents,
- * display the file name and ask for a keystroke.
- */
- error(filename);
- hold_scroll = 0;
- }
- if (first_cmd == NULL || *first_cmd == '\0')
- {
- /*
- * Display the first screen.
- */
- jump_back(1);
- } else
- {
- /*
- * The first_cmd will hopefully redisplay the
- * screen, so we need not display anything yet.
- * Indicate there is nothing yet on the screen.
- */
- pos_clear();
- }
- }
- }
-
- /*
- * Edit the next file in the command line list.
- */
- public void
- next_file(n)
- int n;
- {
- if (curr_ac + n >= ac)
- {
- if (quit_at_eof)
- quit();
- error("No (N-th) next file");
- } else
- edit(av[curr_ac += n]);
- }
-
- /*
- * Edit the previous file in the command line list.
- */
- public void
- prev_file(n)
- int n;
- {
- if (curr_ac - n < 0)
- error("No (N-th) previous file");
- else
- edit(av[curr_ac -= n]);
- }
-
- /*
- * Copy a file directly to standard output.
- * Used if standard output is not a tty.
- */
- static void
- cat_file()
- {
- register int c;
-
- while ((c = ch_forw_get()) != EOF)
- putc(c);
- flush();
- }
-
- /*
- * Entry point.
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char *getenv();
-
-
- /*
- * Process command line arguments and LESS environment arguments.
- * Command line arguments override environment arguments.
- */
- init_option();
- scan_option(getenv("LESS"));
- argv++;
- while ( (--argc > 0) &&
- (argv[0][0] == '-' || argv[0][0] == '+') &&
- argv[0][1] != '\0')
- scan_option(*argv++);
-
- #if EDITOR
- editor = getenv("EDITOR");
- if (editor == NULL || *editor == '\0')
- editor = EDIT_PGM;
- #endif
-
- /*
- * Set up list of files to be examined.
- */
- ac = argc;
- av = argv;
- curr_ac = 0;
-
- /*
- * Set up terminal, etc.
- */
- is_tty = isatty(1);
- if (!is_tty)
- {
- /*
- * Output is not a tty.
- * Just copy the input file(s) to output.
- */
- if (ac < 1)
- {
- edit("-");
- cat_file();
- } else
- {
- do
- {
- edit((char *)NULL);
- if (file >= 0)
- cat_file();
- } while (++curr_ac < ac);
- }
- exit(0);
- }
-
- raw_mode(1);
- get_term();
- open_getc();
- init();
-
- if (back_scroll < 0)
- {
- /* {{ KLUDGE }} */
- back_scroll = sc_height-1;
- if (top_scroll)
- back_scroll--;
- }
-
- if (setjmp(main_loop))
- quit();
- init_signals();
-
- /*
- * Select the first file to examine.
- */
- if (ac < 1)
- edit("-"); /* Standard input */
- else
- {
- /*
- * Try all the files named as command arguments.
- * We are simply looking for one which can be
- * opened without error.
- */
- do
- {
- edit((char *)NULL);
- if (file >= 0)
- /* We can open this file. */
- break;
- putc('\n'); flush();
- } while (++curr_ac < ac);
- }
-
- if (file >= 0)
- commands();
- quit();
- }
-
- /*
- * Exit the program.
- */
- public void
- quit()
- {
- /*
- * Put cursor at bottom left corner, clear the line,
- * reset the terminal modes, and exit.
- */
- lower_left();
- clear_eol();
- deinit();
- flush();
- raw_mode(0);
- exit(0);
- }
- SHAR_EOF
- fi
- if test -f 'makefile.bsd41'
- then
- echo shar: "will not over-write existing file 'makefile.bsd41'"
- else
- cat << \SHAR_EOF > 'makefile.bsd41'
- # Makefile for "less"
- #
- # Invoked as:
- # make all
- # or make install
- # Plain "make" is equivalent to "make all".
- #
- # If you add or delete functions, remake funcs.h by doing:
- # make newfuncs
- # This depends on the coding convention of function headers looking like:
- # " \t public <function-type> \n <function-name> ( ... ) "
- #
- # Also provided:
- # make lint # Runs "lint" on all the sources.
- # make clean # Removes "less" and the .o files.
- # make clobber # Pretty much the same as make "clean".
- #
- # make pager_patch # makes PAGER environment variable
- # make install_pager_patch # catcher and installs it (see below)
-
- ##########################################################################
- # System-specific parameters
- ##########################################################################
-
- # Define XENIX if running under XENIX 3.0
- XENIX = 0
-
- # VOID is 1 if your C compiler supports the "void" type,
- # 0 if it does not.
- VOID = 1
-
- # off_t is the type which lseek() returns.
- # It is also the type of lseek()'s second argument.
- off_t = long
-
- # TERMIO is 1 if your system has /usr/include/termio.h.
- # This is normally the case for System 5.
- # If TERMIO is 0 your system must have /usr/include/sgtty.h.
- # This is normally the case for BSD.
- TERMIO = 0
-
- # SIGSETMASK is 1 if your system has the sigsetmask() call.
- # This is normally the case only for BSD 4.2,
- # not for BSD 4.1 or System 5.
- SIGSETMASK = 0
-
-
- ##########################################################################
- # Optional and semi-optional features
- ##########################################################################
-
- # REGCMP is 1 if your system has the regcmp() function.
- # This is normally the case for System 5.
- # RECOMP is 1 if your system has the re_comp() function.
- # This is normally the case for BSD.
- # If neither is 1, pattern matching is supported, but without metacharacters.
- REGCMP = 0
- RECOMP = 1
-
- # SHELL_ESCAPE is 1 if you wish to allow shell escapes.
- # (This is possible only if your system supplies the system() function.)
- SHELL_ESCAPE = 0
-
- # EDITOR is 1 if you wish to allow editor invocation (the "v" command).
- # (This is possible only if your system supplies the system() function.)
- # EDIT_PGM is the name of the (default) editor to be invoked.
- EDITOR = 0
- EDIT_PGM = /usr/ucb/vi
-
- # parameters to "make install_pager_patch". OLD_PAGER will be moved to
- # OLD_PAGER_NEW_LOCATION and pager_patch (in this directory) will be installed
- # as OLD_PAGER. This patch will allow you to set the environment variable
- # PAGER to specify your personal pager preference (is this a security hole?)
- OLD_PAGER = /usr/ucb/more
- OLD_PAGER_NEW_LOCATION = /usr/ucb/More
-
- # ONLY_RETURN is 1 if you want RETURN to be the only input which
- # will continue past an error message.
- # Otherwise, any key will continue past an error message.
- ONLY_RETURN = 0
-
-
- ##########################################################################
- # Compilation environment.
- ##########################################################################
-
- # LIBS is the list of libraries needed.
- LIBS = -ltermcap
-
- # INSTALL_LESS is a list of the public versions of less.
- # INSTALL_MAN is a list of the public versions of the manual page.
- INSTALL_LESS = /usr/local/less
- INSTALL_MAN = /usr/man/manl/less.l
-
- # OPTIM is passed to the compiler and the loader.
- # It is normally "-O" but may be, for example, "-g".
- OPTIM = -O
-
-
- ##########################################################################
- # Files
- ##########################################################################
-
- SRC1 = main.c option.c prim.c
- SRC2 = ch.c position.c input.c output.c screen.c \
- prompt.c line.c signal.c help.c ttyin.c command.c version.c
- SRC = $(SRC1) $(SRC2)
- OBJ = main.o option.o prim.o ch.o position.o input.o output.o screen.o \
- prompt.o line.o signal.o help.o ttyin.o command.o version.o
-
-
- ##########################################################################
- # Rules
- ##########################################################################
-
- DEFS = "-DTERMIO=$(TERMIO)" \
- "-DSIGSETMASK=$(SIGSETMASK)" \
- "-Doff_t=$(off_t)" "-DVOID=$(VOID)" \
- "-DREGCMP=$(REGCMP)" "-DRECOMP=$(RECOMP)" \
- "-DSHELL_ESCAPE=$(SHELL_ESCAPE)" \
- "-DEDITOR=$(EDITOR)" "-DEDIT_PGM=\"$(EDIT_PGM)\"" \
- "-DONLY_RETURN=$(ONLY_RETURN)" \
- "-DXENIX=$(XENIX)" \
- "-DOLD_PAGER_NEW_LOCATION=\"$(OLD_PAGER_NEW_LOCATION)\""
-
- CFLAGS = $(OPTIM) $(DEFS)
-
-
- all: less
-
- less: $(OBJ)
- cc $(OPTIM) -o less $(OBJ) $(LIBS)
-
- install: install_man install_less
-
- install_man: less.l
- for f in $(INSTALL_MAN); do rm -f $$f; cp less.l $$f; done
- touch install_man
-
- install_less: less
- for f in $(INSTALL_LESS); do rm -f $$f; cp less $$f; done
- touch install_less
-
- pager_patch: pager_patch.c
- cc $(CFLAGS) -s -o pager_patch pager_patch.c
-
- install_pager_patch: pager_patch
- if [ -s $(OLD_PAGER) -a ! -s $(OLD_PAGER_NEW_LOCATION) ]; then \
- mv $(OLD_PAGER) $(OLD_PAGER_NEW_LOCATION); \
- cp pager_patch $(OLD_PAGER); \
- fi
- touch install_pager_patch
-
- $(OBJ): less.h funcs.h
-
- lint:
- lint -hp $(DEFS) $(SRC)
-
- newfuncs:
- mv funcs.h funcs.h.OLD
- awk -f mkfuncs.awk $(SRC) >funcs.h
-
- clean:
- rm -f $(OBJ) less pager_patch
-
- clobber:
- rm -f *.o less pager_patch install_less install_man install_pager_patch
-
- shar:
- shar -v INSTALLATION less.l makefile.* *.h *.awk $(SRC1) > less.shar.a
- shar -v $(SRC2) pager_patch.c > less.shar.b
- SHAR_EOF
- fi
- if test -f 'makefile.bsd42'
- then
- echo shar: "will not over-write existing file 'makefile.bsd42'"
- else
- cat << \SHAR_EOF > 'makefile.bsd42'
- # Makefile for "less"
- #
- # Invoked as:
- # make all
- # or make install
- # Plain "make" is equivalent to "make all".
- #
- # If you add or delete functions, remake funcs.h by doing:
- # make newfuncs
- # This depends on the coding convention of function headers looking like:
- # " \t public <function-type> \n <function-name> ( ... ) "
- #
- # Also provided:
- # make lint # Runs "lint" on all the sources.
- # make clean # Removes "less" and the .o files.
- # make clobber # Pretty much the same as make "clean".
- #
- # make pager_patch # makes PAGER environment variable
- # make install_pager_patch # catcher and installs it (see below)
-
-
- ##########################################################################
- # System-specific parameters
- ##########################################################################
-
- # Define XENIX if running under XENIX 3.0
- XENIX = 0
-
- # VOID is 1 if your C compiler supports the "void" type,
- # 0 if it does not.
- VOID = 1
-
- # off_t is the type which lseek() returns.
- # It is also the type of lseek()'s second argument.
- off_t = long
-
- # TERMIO is 1 if your system has /usr/include/termio.h.
- # This is normally the case for System 5.
- # If TERMIO is 0 your system must have /usr/include/sgtty.h.
- # This is normally the case for BSD.
- TERMIO = 0
-
- # SIGSETMASK is 1 if your system has the sigsetmask() call.
- # This is normally the case only for BSD 4.2,
- # not for BSD 4.1 or System 5.
- SIGSETMASK = 1
-
-
- ##########################################################################
- # Optional and semi-optional features
- ##########################################################################
-
- # REGCMP is 1 if your system has the regcmp() function.
- # This is normally the case for System 5.
- # RECOMP is 1 if your system has the re_comp() function.
- # This is normally the case for BSD.
- # If neither is 1, pattern matching is supported, but without metacharacters.
- REGCMP = 0
- RECOMP = 1
-
- # SHELL_ESCAPE is 1 if you wish to allow shell escapes.
- # (This is possible only if your system supplies the system() function.)
- SHELL_ESCAPE = 0
-
- # EDITOR is 1 if you wish to allow editor invocation (the "v" command).
- # (This is possible only if your system supplies the system() function.)
- # EDIT_PGM is the name of the (default) editor to be invoked.
- EDITOR = 0
- EDIT_PGM = /usr/ucb/vi
-
- # parameters to "make install_pager_patch". OLD_PAGER will be moved to
- # OLD_PAGER_NEW_LOCATION and pager_patch (in this directory) will be installed
- # as OLD_PAGER. This patch will allow you to set the environment variable
- # PAGER to specify your personal pager preference (is this a security hole?)
- OLD_PAGER = /usr/ucb/more
- OLD_PAGER_NEW_LOCATION = /usr/ucb/More
-
- # ONLY_RETURN is 1 if you want RETURN to be the only input which
- # will continue past an error message.
- # Otherwise, any key will continue past an error message.
- ONLY_RETURN = 0
-
-
- ##########################################################################
- # Compilation environment.
- ##########################################################################
-
- # LIBS is the list of libraries needed.
- LIBS = -ltermcap
-
- # INSTALL_LESS is a list of the public versions of less.
- # INSTALL_MAN is a list of the public versions of the manual page.
- INSTALL_LESS = /usr/local/less
- INSTALL_MAN = /usr/man/manl/less.l
-
- # OPTIM is passed to the compiler and the loader.
- # It is normally "-O" but may be, for example, "-g".
- OPTIM = -O
-
-
- ##########################################################################
- # Files
- ##########################################################################
-
- SRC1 = main.c option.c prim.c
- SRC2 = ch.c position.c input.c output.c screen.c \
- prompt.c line.c signal.c help.c ttyin.c command.c version.c
- SRC = $(SRC1) $(SRC2)
- OBJ = main.o option.o prim.o ch.o position.o input.o output.o screen.o \
- prompt.o line.o signal.o help.o ttyin.o command.o version.o
-
-
- ##########################################################################
- # Rules
- ##########################################################################
-
- DEFS = "-DTERMIO=$(TERMIO)" \
- "-DSIGSETMASK=$(SIGSETMASK)" \
- "-Doff_t=$(off_t)" "-DVOID=$(VOID)" \
- "-DREGCMP=$(REGCMP)" "-DRECOMP=$(RECOMP)" \
- "-DSHELL_ESCAPE=$(SHELL_ESCAPE)" \
- "-DEDITOR=$(EDITOR)" "-DEDIT_PGM=\"$(EDIT_PGM)\"" \
- "-DONLY_RETURN=$(ONLY_RETURN)" \
- "-DXENIX=$(XENIX)" \
- "-DOLD_PAGER_NEW_LOCATION=\"$(OLD_PAGER_NEW_LOCATION)\""
-
- CFLAGS = $(OPTIM) $(DEFS)
-
-
- all: less
-
- less: $(OBJ)
- cc $(OPTIM) -o less $(OBJ) $(LIBS)
-
- install: install_man install_less
-
- install_man: less.l
- for f in $(INSTALL_MAN); do rm -f $$f; cp less.l $$f; done
- touch install_man
-
- install_less: less
- for f in $(INSTALL_LESS); do rm -f $$f; cp less $$f; done
- touch install_less
-
- pager_patch: pager_patch.c
- cc $(CFLAGS) -s -o pager_patch pager_patch.c
-
- install_pager_patch: pager_patch
- if [ -s $(OLD_PAGER) -a ! -s $(OLD_PAGER_NEW_LOCATION) ]; then \
- mv $(OLD_PAGER) $(OLD_PAGER_NEW_LOCATION); \
- cp pager_patch $(OLD_PAGER); \
- fi
- touch install_pager_patch
-
- $(OBJ): less.h funcs.h
-
- lint:
- lint -hp $(DEFS) $(SRC)
-
- newfuncs:
- mv funcs.h funcs.h.OLD
- awk -f mkfuncs.awk $(SRC) >funcs.h
-
- clean:
- rm -f $(OBJ) less pager_patch
-
- clobber:
- rm -f *.o less pager_patch install_less install_man install_pager_patch
-
- shar:
- shar -v INSTALLATION less.l makefile.* *.h *.awk $(SRC1) > less.shar.a
- shar -v $(SRC2) pager_patch.c > less.shar.b
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-
-
-